# 大家好呀 我是 吧唧君 喜欢的话点个关注呀 这里不建议转太大的视频
import cv2  # opencv
import glob
import numpy as np
from datetime import datetime
from PIL import Image  # pillow
from moviepy.editor import *
import time

# # 当前项目根目录，系统自动获取当前目录
# BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "."))

# 最终视频的保存路径
output_video = './完整线稿视频.mp4'


def getMusic(video_name):
    """
    获取指定视频的音频
    :param video_name: 视频名称
    :return: 音频对象
    """
    # 读取视频文件
    video = VideoFileClip(video_name)
    # 返回音频
    return video.audio


def addMusic(video_name, audio):
    """实现混流，给video_name添加音频"""
    # 读取视频
    video = VideoFileClip(video_name)
    # 设置视频的音频
    video = video.set_audio(audio)
    # 保存新的视频文件
    video.write_videofile(output_video)


def line_to_video(fps, save_path, line_path, max_index, wide, high):
    """ 线稿转视频
    :param fps: 视频帧数与原视频保持一致
    :param save_path: 储存路径
    :param line_path: 线稿路径
    :param max_index: 总帧数
    :param wide: 视频宽
    :param high: 视频高
    :return:
    """
    # 将line文件里的图片转换成视频的方法
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    videoWriter = cv2.VideoWriter(save_path, fourcc, fps, (wide, high))
    imgs = glob.glob(line_path + "/*.jpg")
    # frames_num = len(imgs)
    for i in range(max_index):
        if os.path.isfile("%s/%d.jpg" % (line_path, i)):
            frame = cv2.imread("%s/%d.jpg" % (line_path, i))
            videoWriter.write(frame)
    videoWriter.release()
    return


def change_line(file_name, file_walk):
    """
    :param file_name: 文件名称
    :param file_walk: 文件路径
    :return:
    """
    a = np.asarray(Image.open(file_walk).convert('L')).astype('float')

    # 根据灰度变化来模拟人视觉的明暗程度
    depth = 10.  # 预设虚拟深度值10
    grad = np.gradient(a)  # 提取梯度值
    grad_x, grad_y = grad  # 提取x y 的梯度值

    # 利用像素之间的梯度值和虚拟深度值对图像进行重构
    grad_x = grad_x * depth / 100.
    grad_y = grad_y * depth / 100.

    A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1.)
    uni_x = grad_x / A
    uni_y = grad_y / A
    uni_z = 1. / A

    vec_el = np.pi / 2.2  # 光源的俯视角度 弧度值
    vec_az = np.pi / 4  # 光源的防线角度 弧度值
    dx = np.cos(vec_el) * np.cos(vec_az)  # 光源对x轴的影响
    dy = np.cos(vec_el) * np.sin(vec_az)  # 光源对y轴的影响
    dz = np.sin(vec_el)  # 光源对z轴的影响

    b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)  # 光源归一话
    b = b.clip(0, 255)  # 避免数据越界
    im = Image.fromarray(b.astype('uint8'))  # 图像重构
    save_file_walk = os.path.join('./line', file_name)
    im.save(save_file_walk)


def video_to_picture(path):
    # 将视频分成一阵一阵储存起来
    videoCapture = cv2.VideoCapture()
    videoCapture.open(path)
    wide = int(videoCapture.get(propId=cv2.CAP_PROP_FRAME_WIDTH))
    high = int(videoCapture.get(propId=cv2.CAP_PROP_FRAME_HEIGHT))

    # 帧率
    fps = videoCapture.get(cv2.CAP_PROP_FPS)
    # 总帧数
    frames = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT)
    # print("fps=", int(fps), "frames=", int(frames))

    for i in range(int(frames)):
        ret, frame = videoCapture.read()
        cv2.imwrite("./shanyi_yuan/{}.jpg".format(i), frame)
        # 转换线稿
        change_line('{}.jpg'.format(i), './shanyi_yuan/{}.jpg'.format(i))

    return fps, frames, wide, high


def check_file():
    # 检测文件夹是否存在
    if not os.path.exists('./line'):
        os.mkdir('line')
    if not os.path.exists('./shanyi_yuan'):
        os.mkdir('shanyi_yuan')


def main():

    # 1 先将 视频装换成 一帧一帧的图片
    print('视频分割成一帧帧的图片并转换成线稿-------')
    # 转换线稿 并返回 合成视频需要的参数 frames 为总帧数
    fps, frames, wide, high = video_to_picture("shanyi.mp4")

    # 2 最后 将线稿图 合成为视频
    print('正在将线稿转换成视频---------')
    line_to_video(int(fps), "线稿视频.mp4", 'line', int(frames), wide, high)
    print('正在将合成音频---------')
    audio = getMusic('./shanyi.mp4')
    addMusic('./线稿视频.mp4', audio)


if __name__ == '__main__':
    t1 = datetime.now()
    check_file()
    main()
    t2 = datetime.now()
    print("Time cost = ", (t2 - t1))
    print("完整线稿视频已生成 !!!！！！")
